//
//  VIPSignalManager.m
//  TTProduct
//
//  Created by My mac on 2019/8/1.
//  Copyright © 2019年 TTProduct. All rights reserved.
//

#import "VIPSignalManager.h"
#import "VIPRoomManager.h"
#import "VIPIMManager.h"
#import "VIPAgoraManager.h"  // 0
#import "VIPIMTeamManager.h" // 1
#import "VIPIMChatroomManager.h" // 2
#import "VIPPCH.h"

@interface VIPSignalManager ()

@property (strong, nonatomic) NSMutableArray *receiveResponse; // 接收到的信令去重用的

@property (strong, nonatomic) NSArray *signals;
@property (nonatomic, assign) NSUInteger uid;
@property (strong, nonatomic) NSMutableArray *signalings; // 全部的信令通道

@property (strong, nonatomic) NSMutableArray *loginedSuccess;
@property (strong, nonatomic) NSMutableArray *loginedOutErrors;

@end

@implementation VIPSignalManager

- (void)loginedLostConnection {
    WS(weakSelf)
    NSMutableArray *loginedSuccess = [self.loginedSuccess mutableCopy];
    for (VIPBaseSignaling *signaling in loginedSuccess) {
        [signaling loginedLostConnectionCompletion:^(VIPMessage * _Nonnull message) {
            [VIPWrite writeLogWithFormat:@"%s [signaling loginedLostConnectionCompletion] - vendor: %@ message: %@", __func__, signaling.signaingName, message.failedText];
            // 重连成功
            if (message == nil) {
                [VIPWrite writeLogWithFormat:@"%s [signaling loginedLostConnectionCompletion] - relogin vendor: %@ success", __func__, signaling.signaingName];
                
                weakSelf.signalingLogout(message);
                [weakSelf.loginedOutErrors removeObject:signaling];
                for (VIPBaseSignaling *signaling in self.loginedOutErrors) {
                    [VIPWrite writeLogWithFormat:@"%s [signaling loginedLostConnectionCompletion] - remaining vendor: %@ fiald", __func__, signaling.signaingName];
                }
                return ;
            }
            
            if (message.status == VIPSignalCodeLogout) {
                [VIPWrite writeLogWithFormat:@"%s [signaling loginedLostConnectionCompletion] - vendor: %@ logout", __func__, signaling.signaingName];
                [weakSelf.loginedOutErrors removeObject:signaling];
                [weakSelf.loginedSuccess removeObject:signaling];
                return ;
            }
            
            // 被踢
            if (message.status == VIPSignalCodeKiched) {
                [VIPWrite writeLogWithFormat:@"%s [signaling loginedLostConnectionCompletion] - vendor: %@ kiched", __func__, signaling.signaingName];
                [weakSelf.loginedSuccess removeObject:signaling];
                [weakSelf.loginedOutErrors removeObject: signaling];
                if (weakSelf.loginedSuccess.count != 0) {
                    return ;
                }
                // 全部被踢
                [VIPWrite writeLogWithFormat:@"%s [signaling loginedLostConnectionCompletion] - all banned", __func__];
                if (!weakSelf.signaingDidBanned) return;
                weakSelf.signaingDidBanned(); // 被踢
                return;
            }
            if ([weakSelf.loginedOutErrors containsObject:signaling]) return;
            
            // 掉线
            [weakSelf.loginedOutErrors addObject:signaling];
            for (VIPBaseSignaling *sign in self.loginedOutErrors) {
                [VIPWrite writeLogWithFormat:@"%s [signaling loginedLostConnectionCompletion] - vendor: %@ off line", __func__, sign.signaingName];
            }
            
            // 全部掉线 弹框等待, 后台轮循连接
            if (weakSelf.loginedOutErrors.count == weakSelf.loginedSuccess.count) {
                [VIPWrite writeLogWithFormat:@"%s [signaling loginedLostConnectionCompletion] - all off line", __func__];
                if (weakSelf.signalingLogout == nil) return;
                weakSelf.signalingLogout(message);
            }
        }];
    }
}

- (void)leaveRoom { // 退出房间 并且 退出信令
    [VIPAPIService exitChatRoom:@"" creater:@"" lessonId:@"" agType:0 block:^(BOOL result) {
        if (!result) return;
        for (VIPBaseSignaling *signaling in self.loginedSuccess) {
            [VIPWrite writeLogWithFormat:@"%s [VIPAPIService exitChatRoom] - vendor: %@ leave room", __func__, signaling.signaingName];
            [signaling leaveRoomCompletion:^(VIPMessage * _Nonnull message) {
                [VIPWrite writeLogWithFormat:@"%s [signaling leaveRoomCompletion] - vendor: %@ leave room success", __func__, signaling.signaingName];
                [signaling logoutCompletion:nil];
            }];
        }
    }];
}

// 退出房间, 不退出信令
- (void)leaveRoomCompletion:(nullable VIPCompletionHandler)completion { // 退出房间
    __block int i = 0;
    WS(weakSelf)
    for (VIPBaseSignaling *signaling in self.loginedSuccess) {
        if (signaling.status != VIPSignalStateLoginOK) continue;
        
        [VIPWrite writeLogWithFormat:@"%s - vendor: %@ leave room", __func__, signaling.signaingName];
        [signaling leaveRoomCompletion:^(VIPMessage * _Nonnull message) {
            [VIPWrite writeLogWithFormat:@"%s [signaling leaveRoomCompletion] - vendor: %@ leave room success", __func__, signaling.signaingName];
            i++;
            if (i != weakSelf.loginedSuccess.count || completion == nil) return ;
            VIPMessage *completionMessage = [VIPMessage messageWithFailedText:@"退出房间" status:VIPSignalCodeSuccess];
            completion(completionMessage);
        }];
    }
}

// 退出信令
- (void)logoutSignaling {
    for (VIPBaseSignaling *signaling in self.loginedSuccess) {
        [signaling logoutCompletion:nil];
    }
}

- (void)bindingRoomInfo:(VIPRoomModel *)room {
    self.signals = room.signals;
    self.uid = room.uid;
}

- (void)initializeSignalingCompletion:(VIPCompletionHandler)completion {
    _signalings = [NSMutableArray array];
    _loginedSuccess = nil;
    _loginedOutErrors = nil;
    _receiveResponse = nil;
    
    [self bindingRoomInfo:[VIPRoomManager shareManager].room];
    
    [self initialize];
    
    // 如果信令通道为空
    if (self.signalings.count == 0) {
        if (completion == nil) { return; }
        VIPMessage *completionMessage = [VIPMessage messageWithFailedText:@"信令登录失败, 错误码: AN[-999]" status:VIPSignalCodeLoginError];
        completion(completionMessage);
        return;
    }
    
    WS(weakSelf)
    [self loginSignalingCompletion:^(VIPMessage * _Nullable message) {
        if (message) {
            completion(message);
            return ;
        }
        [weakSelf initializeResponse];
        [weakSelf loginedLostConnection];
        [weakSelf loginedTokenTimeout];
        
        completion(nil);
    }];
}

// 频道内发送
- (void)sendMessageChannelMsg:(NSString*)msg {
    [self sendMessageChannelMsg:msg completion:nil];
}

// 频道内发送
- (void)sendMessageChannelMsg:(NSString*)msg completion:(nullable VIPCompletionHandler)completion {
    
    [VIPWrite writeLogWithFormat:@"%s - send msg: %@", __func__, msg];
    
    for (VIPBaseSignaling *signaling in self.loginedSuccess) {
        if (signaling.status != VIPSignalStateLoginOK) continue;
        signaling.signal.msg = msg;
        [signaling sendMessageCompletion:^(VIPMessage * _Nonnull message) {
            NSString *statusString = @"success";
            if (message) {
                statusString = @"fiald";
            }
            
            [VIPWrite writeLogWithFormat:@"%s [signaling sendMessageCompletion] - vendor: %@ send msg: %@ %@", __func__, signaling.signaingName, msg, statusString];
            if (!completion) return ;
            completion(message);
        }];
    }
}

- (void)initialize {
    for (VIPSignalModel *signal in self.signals) {
        signal.account = [NSString stringWithFormat:@"%ld", self.uid];
        [self factorySignaling:signal];
    }
}

- (BOOL)allSignalingStatus {
    for (VIPBaseSignaling *signaling in self.signalings) {
        if (signaling.status == VIPSignalStateLogining) { return NO; }
    }
    
    return YES;
}

- (void)loginSignalingCompletion:(VIPCompletionHandler)completion {
    WS(weakSelf)
    void (^logintFaildBack)(VIPBaseSignaling *, VIPMessage *) = ^(VIPBaseSignaling *signaling, VIPMessage *message) {
        signaling.message = message;
        bool signalingState = [weakSelf allSignalingStatus];
        // 还没有结束
        if (!signalingState || completion == nil) return;
        NSString *msg = [weakSelf loginErrorMessage];
        // 代表有信令登陆成功了
        if (msg.length == 0) {
            completion(nil);
            [VIPWrite writeLogWithFormat:@"%s [^logintFaildBack] - one of the signaling failed: %@", __func__, signaling.signaingName];
            return;
        }
        // 代表全部登陆失败
        VIPMessage *completionMessage = [VIPMessage messageWithFailedText:msg status:VIPSignalCodeLoginError];
        completion(completionMessage);
    };
    
    for (VIPBaseSignaling *signaling in self.signalings) {
        [VIPWrite writeLogWithFormat:@"%s  - signaling start login: %@", __func__, signaling.signaingName];
        
        [signaling loginCompletion:^(VIPMessage * _Nonnull message) {
            // 登陆失败
            if (message) {
                [VIPWrite writeLogWithFormat:@"%s [signaling loginCompletion] - signaling %@ login result: fiald", __func__, signaling.signaingName];
                logintFaildBack(signaling, message);
                return;
            }
            
            [VIPWrite writeLogWithFormat:@"%s [signaling loginCompletion] - signaling %@ login result: success", __func__, signaling.signaingName];
            
            [VIPWrite writeLogWithFormat:@"%s [signaling loginCompletion] - signaling %@ about to enter the room", __func__, signaling.signaingName];
            
            // 进入房间
            [weakSelf joinRoomWithSignaling:signaling completion:^(VIPMessage * _Nullable message) {
                if (message) {
                    [VIPWrite writeLogWithFormat:@"%s [joinRoomWithSignaling] - signaling %@ join room fiald", __func__, signaling.signaingName];
                    
                    logintFaildBack(signaling, message);
                    return;
                }
                
                [VIPWrite writeLogWithFormat:@"%s [joinRoomWithSignaling] - signaling %@ join room success", __func__, signaling.signaingName];
                // 登陆成功
                [weakSelf.loginedSuccess addObject:signaling];
                
                for (VIPBaseSignaling *sign in self.loginedSuccess) {
                    [VIPWrite writeLogWithFormat:@"%s [joinRoomWithSignaling] - signaling %@ login success", __func__, sign.signaingName];
                }
                bool signalingState = [weakSelf allSignalingStatus];
                // 还没有结束
                if (!signalingState || completion == nil) return;
                completion(nil);
                
                [VIPWrite writeLogWithFormat:@"%s [joinRoomWithSignaling] - signaling login result: success", __func__];
            }];
        }];
    }
}

- (NSString *)loginErrorMessage {
    NSMutableString *message = [NSMutableString string];
    [message appendFormat:@"信令登陆失败, 错误码: "];
    for(VIPBaseSignaling *signaling in self.signalings) {
        // 有成功的 就返回 nil
        if (signaling.status == VIPSignalStateLoginOK) {
            message = nil;
            break;
        }
        [message appendFormat:@"%@[%d]", signaling.flag, (int)signaling.message.ecode];
        if (signaling != self.signalings.lastObject) { [message appendFormat:@", "]; }
    }
    
    return message;
}

- (void)joinRoomWithSignaling:(VIPBaseSignaling *)signaling completion:(VIPCompletionHandler)completion { // 单个进入房间
    [signaling joinRoomCompletion:^(VIPMessage * _Nonnull message) {
        if (completion) completion(message);
    }];
}

- (void)initializeResponse {
    WS(weakSelf)
    for (VIPBaseSignaling *signaling in self.loginedSuccess) {
        [signaling setResponse:^(NSString * _Nonnull account, NSString * _Nonnull signalingString, NSString * _Nonnull signaingName) {
            
            if (!weakSelf.signaingResponse) return;
            VIPSignalingModel *signalingModel = [VIPSignalingModel responseMessage:signalingString account:account];
            if ([weakSelf.receiveResponse containsObject:signalingModel.msgID] ||
                signaling.status == VIPSignalStateLoseConnection) return;
            [VIPWrite writeLogWithFormat:@"%s [signaling response] - vendor:%@, signalingString: %@", __func__, signaingName, signalingString];
            [weakSelf.receiveResponse addObject:signalingModel.msgID];
            weakSelf.signaingResponse(account, signalingModel);
        }];
    }
}

- (void)loginedTokenTimeout {
    WS(weakSelf)
    for (VIPBaseSignaling *signaling in self.loginedSuccess) {
        if (signaling.signal.type != VIPSignalServerAgora) return;
        [signaling setTokenDidFailure:^{
            if (!weakSelf.tokenDidFailure) return ;
            weakSelf.tokenDidFailure();
            return ;
        }];
    }
}

- (void)factorySignaling:(id)obj {
    VIPSignalModel *signal = (VIPSignalModel *)obj;
    VIPBaseSignaling *signaling;
    if (signal.type == VIPSignalServerAgora) { // 声网
        signaling = [VIPAgoraManager shareManager];
    }
    
    if (signal.type == VIPSignalServerNIMTeam) { // 网易, 群组方式
        signaling = [VIPIMTeamManager shareManager];
    }
    
    if (signal.type == VIPSignalServerNIMMessage) { // 网易, 聊天室方式
        signaling = [VIPIMChatroomManager shareManager];
    }
    
    [signaling registerSignalingSDK:signal];
    
    if ([self.signalings containsObject:signaling]) return;
    [self.signalings addObject:signaling];
}

- (NSMutableArray *)receiveResponse {
    if (!_receiveResponse) {
        _receiveResponse = [NSMutableArray new];
    }
    return _receiveResponse;
}

- (NSMutableArray *)loginedSuccess {
    if (!_loginedSuccess) {
        _loginedSuccess = [NSMutableArray new];
    }
    return _loginedSuccess;
}

- (NSMutableArray *)loginedOutErrors {
    if (!_loginedOutErrors) {
        _loginedOutErrors = [NSMutableArray new];
    }
    return _loginedOutErrors;
}

static VIPSignalManager* _instance = nil;
+ (instancetype)shareManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[super allocWithZone:NULL] init];
    });
    return _instance ;
}

+ (id)allocWithZone:(struct _NSZone *)zone {
    return [VIPSignalManager shareManager];
}

- (id)copyWithZone:(struct _NSZone *)zone {
    return [VIPSignalManager shareManager];
}


@end

